package com.artisan.springuitls.demos;

import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

/**
 * StopWatch 工具类演示
 * 功能：代码耗时统计器
 * 优势：比 System.currentTimeMillis() 更专业，自动计算百分比、可命名任务
 */
@Component
public class StopWatchDemo {

    /**
     * 场景：统计方法执行耗时
     */
    public void monitorOperations() throws InterruptedException {
        System.out.println("\n========== StopWatch Demo ==========");
        
        StopWatch watch = new StopWatch("订单服务监控");
        
        // ✅ 任务 1：查询订单
        watch.start("查询订单");
        queryOrders();
        watch.stop();
        
        // ✅ 任务 2：发送通知
        watch.start("发送通知");
        sendNotifications();
        watch.stop();
        
        // ✅ 任务 3：更新缓存
        watch.start("更新缓存");
        updateCache();
        watch.stop();
        
        // ✅ 输出清晰报告
        System.out.println(watch.prettyPrint());
        
        // 输出总耗时
        System.out.println("\n✓ 总耗时: " + watch.getTotalTimeMillis() + " ms");
        System.out.println("✓ 总耗时(秒): " + watch.getTotalTimeSeconds() + " s");
        System.out.println("✓ 总耗时(纳秒): " + watch.getTotalTimeNanos() + " ns");
    }

    /**
     * 演示基础使用方法
     */
    public void demonstrateBasicUsage() throws InterruptedException {
        System.out.println("\n--- 基础使用方法 ---");
        
        StopWatch watch = new StopWatch("基础示例");
        
        // 启动计时
        watch.start("任务A");
        Thread.sleep(100);
        watch.stop();
        
        watch.start("任务B");
        Thread.sleep(200);
        watch.stop();
        
        // 获取任务信息
        System.out.println("✓ 任务数量: " + watch.getTaskCount());
        
        // 获取最后任务信息
        StopWatch.TaskInfo lastTask = watch.getLastTaskInfo();
        System.out.println("✓ 最后一个任务: " + lastTask.getTaskName());
        System.out.println("✓ 最后任务耗时: " + lastTask.getTimeMillis() + " ms");
        
        // 详细的任务信息
        StopWatch.TaskInfo[] tasks = watch.getTaskInfo();
        for (int i = 0; i < tasks.length; i++) {
            StopWatch.TaskInfo task = tasks[i];
            System.out.println("✓ 任务" + (i+1) + ": " + task.getTaskName() + 
                " - " + task.getTimeMillis() + " ms" +
                " (" + String.format("%.1f", task.getTimeSeconds()) + " s)");
        }
        
        System.out.println();
    }

    /**
     * 演示实际应用场景
     */
    public void demonstrateRealWorldScenario() throws InterruptedException {
        System.out.println("\n--- 实际应用：接口性能监控 ---");
        
        StopWatch watch = new StopWatch("用户注册接口");
        
        // 1. 参数校验
        watch.start("参数校验");
        Thread.sleep(10);
        watch.stop();
        
        // 2. 检查用户是否存在
        watch.start("检查用户是否存在");
        Thread.sleep(50);
        watch.stop();
        
        // 3. 加密密码
        watch.start("加密密码");
        Thread.sleep(100);
        watch.stop();
        
        // 4. 插入数据库
        watch.start("插入数据库");
        Thread.sleep(200);
        watch.stop();
        
        // 5. 发送欢迎邮件
        watch.start("发送欢迎邮件");
        Thread.sleep(150);
        watch.stop();
        
        // 分析性能瓶颈
        System.out.println(watch.prettyPrint());
        System.out.println("\n✓ 性能分析:");
        System.out.println("  - 总耗时: " + watch.getTotalTimeMillis() + " ms");
        
        // 找出最耗时的任务
        StopWatch.TaskInfo[] tasks = watch.getTaskInfo();
        StopWatch.TaskInfo slowestTask = tasks[0];
        for (StopWatch.TaskInfo task : tasks) {
            if (task.getTimeMillis() > slowestTask.getTimeMillis()) {
                slowestTask = task;
            }
        }
        System.out.println("  - 最慢环节: " + slowestTask.getTaskName() + 
            " (" + slowestTask.getTimeMillis() + " ms)");
        
        System.out.println();
    }

    /**
     * 演示嵌套计时场景
     */
    public void demonstrateNestedTiming() throws InterruptedException {
        System.out.println("\n--- 嵌套计时场景 ---");
        
        StopWatch outerWatch = new StopWatch("外层任务");
        
        outerWatch.start("批量处理");
        
        // 内部处理
        for (int i = 1; i <= 3; i++) {
            StopWatch innerWatch = new StopWatch("批次-" + i);
            
            innerWatch.start("读取数据");
            Thread.sleep(20);
            innerWatch.stop();
            
            innerWatch.start("处理数据");
            Thread.sleep(30);
            innerWatch.stop();
            
            System.out.println("✓ " + innerWatch.getId() + " 耗时: " + 
                innerWatch.getTotalTimeMillis() + " ms");
        }
        
        outerWatch.stop();
        
        System.out.println("\n" + outerWatch.prettyPrint());
        System.out.println();
    }

    /**
     * 演示与 AOP 结合使用
     */
    public void demonstrateAopIntegration() {
        System.out.println("\n--- AOP 集成示例 ---");
        
        System.out.println("✓ 在 AOP 中使用 StopWatch:");
        System.out.println("");
        System.out.println("@Around(\"@annotation(TrackTime)\")");
        System.out.println("public Object trackTime(ProceedingJoinPoint pjp) throws Throwable {");
        System.out.println("    StopWatch watch = new StopWatch();");
        System.out.println("    watch.start(pjp.getSignature().toShortString());");
        System.out.println("    try {");
        System.out.println("        return pjp.proceed();");
        System.out.println("    } finally {");
        System.out.println("        watch.stop();");
        System.out.println("        log.info(watch.prettyPrint());");
        System.out.println("    }");
        System.out.println("}");
        
        System.out.println();
    }

    /**
     * 最佳实践和注意事项
     */
    public void printBestPractices() {
        System.out.println("\n========== 最佳实践 ==========");
        System.out.println("✓ 1. 为 StopWatch 设置有意义的 ID");
        System.out.println("✓ 2. 为每个任务设置清晰的名称");
        System.out.println("✓ 3. 记得调用 stop()，否则会抛异常");
        System.out.println("✓ 4. 使用 prettyPrint() 获取格式化报告");
        System.out.println("✓ 5. 结合 AOP 实现全局性能监控");
        System.out.println("✓ 6. 生产环境可结合日志框架记录");
        System.out.println("✓ 7. 不要在高并发场景使用（有性能开销）");
        System.out.println("==========================================\n");
    }

    // 模拟业务方法
    private void queryOrders() throws InterruptedException {
        Thread.sleep(200);
    }

    private void sendNotifications() throws InterruptedException {
        Thread.sleep(150);
    }

    private void updateCache() throws InterruptedException {
        Thread.sleep(100);
    }
}

